package pcp

import (
	"encoding/base64"
	"gitee.com/teval/uts"
	"github.com/forgoer/openssl"
)

func AesCBCEncrypt(value, key, iv string, pad ...string) (string, error) {
	var p = openssl.PKCS5_PADDING
	if len(pad) > 0 {
		p = uts.Nvl(pad[0], p)
	}
	a := NewAesCBCCrypt(key, iv, p)
	return a.Encrypt([]byte(value))
}

func AesCBCDecrypt(value, key, iv string, pad ...string) (string, error) {
	var p = openssl.PKCS5_PADDING
	if len(pad) > 0 {
		p = uts.Nvl(pad[0], p)
	}
	a := NewAesCBCCrypt(key, iv, p)
	return a.Decrypt(value)
}

func AesCBCEncryptOnly(value, key, iv []byte, pad ...string) ([]byte, error) {
	var p = openssl.PKCS5_PADDING
	if len(pad) > 0 {
		p = uts.Nvl(pad[0], p)
	}
	return openssl.AesCBCEncrypt(value, key, iv, p)
}

func AesCBCDecryptOnly(value, key, iv []byte, pad ...string) ([]byte, error) {
	var p = openssl.PKCS5_PADDING
	if len(pad) > 0 {
		p = uts.Nvl(pad[0], p)
	}
	return openssl.AesCBCDecrypt(value, key, iv, p)
}

func NewAesCBCCrypt(key, iv string, pad ...string) (aesCBCCrypt *AesCBCCrypt) {
	aesCBCCrypt = &AesCBCCrypt{
		Key:     []byte(key),
		Iv:      []byte(iv),
		Padding: openssl.PKCS5_PADDING,
	}

	if len(pad) > 0 {
		aesCBCCrypt.Padding = pad[0]
	}

	return
}

type AesCBCCrypt struct {
	Key     []byte
	Iv      []byte
	Padding string
}

func (a *AesCBCCrypt) EncryptOnly(src []byte) (rst []byte, err error) {
	return openssl.AesCBCEncrypt(src, a.Key, a.Iv, a.Padding)
}

func (a *AesCBCCrypt) DecryptOnly(data []byte) (rst []byte, err error) {
	return openssl.AesCBCDecrypt(data, a.Key, a.Iv, a.Padding)
}

func (a *AesCBCCrypt) Encrypt(src []byte) (rst string, err error) {
	dst, err := openssl.AesCBCEncrypt(src, a.Key, a.Iv, a.Padding)
	if err != nil {
		return
	}
	rst = base64.StdEncoding.EncodeToString(dst)
	return
}

func (a *AesCBCCrypt) Decrypt(data string) (rst string, err error) {
	src, err := base64.StdEncoding.DecodeString(data)
	if err != nil {
		return
	}
	dst, err := openssl.AesCBCDecrypt(src, a.Key, a.Iv, a.Padding)
	if err != nil {
		return
	}
	rst = string(dst)
	return
}
